using System;
using System.Collections.Generic;
using System.Globalization;
using NDesk.Options;

namespace Quiki.Console
{
    public class GenerateHtmlCommand : IConsoleCommand
    {
        public GenerateHtmlCommand()
        {
            settings = new DocumentProcessorSettings();
            settings.InputDir = ".";
            settings.OutputDir = "html";
            settings.TemplateFileName = "template.vm.html";
            settings.Recursive = true;

            string exclusionFilterMessage = string.Format(
                CultureInfo.InvariantCulture,
                "a {{regular expression}} specifying which files and directories to exclude when processing. The default filter is: '{0}'.",
                settings.FileExclusionFilter);
 
            options = new OptionSet
                          {
                              { "i|inputdir=", "the root input {directory} where wiki files are. The default is current directory.", x => settings.InputDir = x },
                              { "f|filter=", "file name {filter} to select which files to process. The default is '*.wiki'.", x => settings.FileExclusionFilter = x },
                              { "ex|exclude=", exclusionFilterMessage, x => settings.FileExclusionFilter = x },
                              { "o|outputdir=", "the output {directory} where HTML files will be generated. The default is 'html' directory.", x => settings.OutputDir = x },
                              { "t|template=", "{file name} of the template to use for generating HTML files. The default is 'template.vm.html'.", x => settings.TemplateFileName = x },
                              { "parsefile=", "a {true/false} value indicating whether to generate parse debug files for wiki files. These files are not generated by default.", (bool generate) => settings.GenerateParsingInfoFiles = generate },
                              { "r|recursive=", "a {true/false} value indicating whether to search for wiki files in subdirectories. By default subdirectories are searched.", (bool recursive) => settings.Recursive = recursive },
                              { "p|property=", "specifies a custom property ({key}:{value}) used in the template.", (k, v) => settings.CustomProperties.Set(k, v) },
                              { "lf|linkedfile=", "specifies one or more files which need to be also copied to the output dir (like CSS files)", x => settings.AddLinkedFile(x) },
                              { "ftpserver=", "specifies that the produced files should be uploaded to a FTP server {host} (you must also specify all other FTP settings)", x => settings.FtpServer = x },
                              { "ftpport=", "specifies the {FTP port} (if omitted, the default port is used)", x => settings.FtpServer = x },
                              { "ftpuser=", "specifies the {username} for the FTP server", x => settings.FtpUserName = x },
                              { "ftppwd=", "specifies the {password} for the FTP server user", x => settings.FtpPassword = x },
                              { "ftpdir=", "specifies the {remote directory} on the FTP server where files should be uploaded", x => settings.FtpRemoteDir = x },
                          };
        }

        public string CommandDescription
        {
            get { return "generates static HTML pages from wiki pages"; }
        }

        public string CommandName
        {
            get { return "html"; }
        }

        public int Execute(IEnumerable<string> args)
        {
            VerifyArguments(args);
            GenerateHtmlFiles();

            return 0;
        }

        public void ShowHelp()
        {
            options.WriteOptionDescriptions(System.Console.Out);
        }

        private void VerifyArguments(IEnumerable<string> args)
        {
            List<string> unhandledArguments = options.Parse(args);

            if (unhandledArguments.Count > 0)
                throw new ArgumentException("You specified some unsupported options.");
        }

        private void GenerateHtmlFiles()
        {
            ILogger logger = new ConsoleLogger();
            DocumentProcessor processor = new DocumentProcessor(settings, logger);
            processor.Process();
        }

        private OptionSet options;
        private DocumentProcessorSettings settings;
    }
}